#ifndef MONEY_H
#define MONEY_H

#include <iosfwd>
#include <string>
#include <math.h>


namespace math
{
	/**	Rounds the given number with the specified decimals upwards
		@example assert(3.142 == round(3.141516, 3));
	*/
	double round(double number, int decimals)
	{
		double power = pow(10.0, decimals);
		
		if(number > 0.0)
			return static_cast<long>(number * power + 0.5) / power;
		else
			return static_cast<long>(number * power - 0.5) / power;
	}
}

namespace money
{

class Currency
{
public:
	Currency(const std::string &code, const std::string &symbol = "$", double multiplier = 1.0, char decimals = 2, double amount = 0.0)
		: m_code(code), m_symbol(symbol), m_multiplier(multiplier), m_decimals(decimals), m_amount(amount) { }
	
	float getMultiplier() const { return m_multiplier; }
	char getDecimals() const { return m_decimals; }
	std::string getSymbol() const { return m_symbol; }
	std::string getCode() const { return m_code; }
	float getAmount() const { return m_amount; }
	
	
	bool operator==(const Currency& rhs) const
	{
		// bool equal = math::round(getAmount(), getDecimals()) == math::round(rhs.getAmount(), rhs.getDecimals());
		// TODO
		return false;
	}
	
	bool operator!=(const Currency &rhs) const
	{
		return !(*this == rhs);
	}
	
	bool operator==(const double rhs) const
	{
		return math::round(getAmount(), getDecimals()) == rhs;
	}
	
	bool operator!=(const double rhs) const
	{
		return !(*this == rhs);
	}
	
	friend std::ostream& operator<<(std::ostream &os, const Currency& rhs)
	{
		os << math::round(rhs.getAmount(), rhs.getDecimals());
		return os;
	}
	
	const Currency times(double multiplier) const
	{
		return Currency(m_code, m_symbol, m_multiplier, m_decimals, m_amount * multiplier);
	}

	
protected:
	double m_multiplier;
	char m_decimals;
	double m_amount;
	
	std::string m_symbol;
	std::string m_code;
};

struct Euro : public Currency 
{
	Euro(double amount) : Currency("EUR", "e", 1.4, 2, amount) { }
};

struct Dollar : public Currency 
{
	Dollar(double amount) : Currency("USD", "$", 1.0, 2, amount) { }
};

struct Peso : public Currency 
{
	Peso(double amount) : Currency("ARS", "$", 3.12, 2, amount) { }
};

struct Yen : public Currency 
{
	Yen(double amount) : Currency("JPY", "Y", 112.0, 0, amount) { }
};

}

#endif
